package com.party.web.biz.activity;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.party.common.constant.Constant;
import com.party.common.redis.StringJedis;
import com.party.common.utils.BigDecimalUtils;
import com.party.common.utils.DateUtils;
import com.party.common.utils.StringUtils;
import com.party.core.exception.BusinessException;
import com.party.core.model.BaseModel;
import com.party.core.model.YesNoStatus;
import com.party.core.model.activity.Activity;
import com.party.core.model.crowdfund.Project;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.member.PackageCount;
import com.party.core.model.notify.Event;
import com.party.core.model.notify.InstanceWay;
import com.party.core.model.notify.TargetTemplate;
import com.party.core.model.notify.TargetTemplateType;
import com.party.core.model.quartz.QuartzDataMap;
import com.party.core.model.system.TargetType;
import com.party.core.service.activity.IActivityService;
import com.party.core.service.crowdfund.IProjectService;
import com.party.core.service.crowdfund.ITargetTemplateService;
import com.party.core.service.member.IMemberGroupService;
import com.party.core.service.member.IPackageCountService;
import com.party.core.service.member.IThirdMemberService;
import com.party.core.service.notify.IEventService;
import com.party.core.service.quartz.IQuartzDataMapService;
import com.party.notify.notifyPush.activity.ActivitySendFactory;
import com.party.notify.notifyPush.activity.INotifyActivitySendService;
import com.party.web.biz.file.FileBizService;
import com.party.web.biz.quartz.IScheduleJobService;
import com.party.web.biz.quartz.impl.SchsduleService;
import com.party.web.biz.system.member.MemberGroupBizService;
import com.party.web.web.dto.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 *
 * 活动业务接口 Created by wei.li
 *
 * @date 2017/3/22 0022
 * @time 17:44
 */
@Service
public class ActivityBizService {

	@Autowired
	private FileBizService fileBizService;


	@Autowired
	private IProjectService projectService;

	@Autowired
	private ITargetTemplateService targetTemplateService;

	@Autowired
	private IActivityService activityService;

	@Autowired
	private ActivitySendFactory activitySendFactory;

	@Autowired
	private IThirdMemberService thirdMemberService;

	@Autowired
    private IPackageCountService packageCountService;

	@Autowired
	private IScheduleJobService scheduleJobService;

	@Autowired
	private IEventService eventService;

	@Autowired
	private IQuartzDataMapService quartzDataMapService;

	@Autowired
	private IMemberGroupService memberGroupService;

	@Autowired
	private MemberGroupBizService memberGroupBizService;

	@Autowired
	private StringJedis stringJedis;

	private static Logger logger = LoggerFactory.getLogger(ActivityBizService.class);

	/**
	 * 拼接分销连接
	 *
	 * @param id
	 *            活动编号
	 * @param memberId
	 *            创建者
	 * @return 分销连接
	 */
	public String getDistributionUrl(String id, String memberId) {
		StringBuilder stringBuilder = new StringBuilder("hd/hd_distribution.html?");
		stringBuilder.append("id=").append(id).append("&parentId=").append("0").append("&distributorId=").append(memberId);
		return stringBuilder.toString();
	}

	/**
	 * 众筹项目众筹了多少资金
	 *
	 * @param targetId
	 *            目标编号
	 * @return 资金
	 */
	public float actualAmountForTargetId(String targetId) {
		List<Project> projectList = projectService.listForTargetId(targetId);
		float actualAmount = 0f;
		for (Project project : projectList) {
			actualAmount = BigDecimalUtils.add(actualAmount, project.getActualAmount());
		}
		actualAmount = BigDecimalUtils.round(actualAmount, 2);
		return actualAmount;
	}

	/**
	 * 获取目标模板
	 * @param targetId 模板编号
	 * @param type 类型
	 * @return 模板编号
	 */
	public TargetTemplate getTemplate(String targetId, Integer type){
		type = null == type ? TargetTemplateType.ACT_STATUS_AUDITING.getCode() : type;
		TargetTemplate targetTemplate = targetTemplateService.findByTargetId(targetId, type);
		if (null == targetTemplate){
			targetTemplate = new TargetTemplate();
			targetTemplate.setType(type);
			targetTemplate.setTargetId(targetId);
		}
		return targetTemplate;
	}

	/**
	 * 发送消息and保存模板
	 * @param id 目标模板id
	 */
	public boolean send(String id) {
		TargetTemplate targetTemplate = targetTemplateService.get(id);
		if (Strings.isNullOrEmpty(targetTemplate.getTemplate())) {
			throw new BusinessException("模板内容不能为空");
		}
		Activity activity = activityService.get(targetTemplate.getTargetId());
		if (null == activity) {
			throw new BusinessException("找不到活动");
		}

		return this.activityRealSend(targetTemplate, activity.getMember());
	}

	/**
	 * 发送消息and保存模板
	 * @param targetTemplate 目标模板
	 */
	public boolean sendAndSave(TargetTemplate targetTemplate){
		if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
			throw new BusinessException("模板内容不能为空");
		}
		Activity activity = activityService.get(targetTemplate.getTargetId());
		if (null == activity){
			throw new BusinessException("找不到众筹项目");
		}

		//保存
		targetTemplate.setId(null);
		targetTemplate.setInitiatorId(activity.getMember());
		Date now = new Date();
		targetTemplate.setCreateDate(now);
		targetTemplate.setUpdateDate(now);
		targetTemplate.setSendTime(now);
		targetTemplateService.insert(targetTemplate);

		return this.activityRealSend(targetTemplate, activity.getMember());
	}

	public String save(TargetTemplate targetTemplate) {
		if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
			throw new BusinessException("模板内容不能为空");
		}
		Activity activity = activityService.get(targetTemplate.getTargetId());
		if (null == activity){
			throw new BusinessException("找不到众筹项目");
		}

		//保存
		targetTemplate.setInitiatorId(activity.getMember());
		return targetTemplateService.insert(targetTemplate);
	}

	/**
	 * 获取用户发布的活动数量
	 * @param memberId
	 * @return
	 */
	public Integer getMaxCount(String memberId, Integer isCrowdfunded){
		Activity activity = new Activity();
		activity.setMemberId(memberId);
		activity.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
		activity.setIsCrowdfunded(isCrowdfunded);
		return activityService.getCount(activity);
	}


	public boolean generateAccount(List<String> thirdList, Integer account, List<Integer> lists) {
		lists.add(account);
		boolean flag = true;
		for (String str : thirdList) {
			if (account.toString().equals(str)) {
				flag = false;
				lists.remove(Integer.valueOf(str));
				break;
			} else {
				flag = true;
			}
		}

		if (flag == false) {
			account = (int) ((Math.random() * 9 + 1) * 100000);
			flag = generateAccount(thirdList, account, lists);
		}
		return flag;
	}

	/**
	 * 生成随机数字和字母,
	 * @param length
	 * @return
	 */
	public String getStringRandom(int length) {
		String val = "";
		Random random = new Random();

		//参数length，表示生成几位随机数
		for (int i = 0; i < length; i++) {
			String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
			//输出字母还是数字
			if ("char".equalsIgnoreCase(charOrNum)) {
				//输出是大写字母还是小写字母
				int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
				val += (char) (random.nextInt(26) + temp);
			} else if ("num".equalsIgnoreCase(charOrNum)) {
				val += String.valueOf(random.nextInt(10));
			}
		}
		return val;
	}

	/**
	 * 生成信息
	 * @param activityId 项目id
	 * @return
	 */
	public Map<String, Object> generateInfo(String activityId) {
		Map<String, Object> result = Maps.newHashMap();
		Integer account = (int) ((Math.random() * 9 + 1) * 100000);
		List<String> thirdList = thirdMemberService.allAccount();
		List<Integer> lists = Lists.newArrayList();
		generateAccount(thirdList, account, lists);
		result.put("account", lists.get(0));
		String password = getStringRandom(6);
		result.put("password", password.toLowerCase());
		String alias = "/activity/zcActivity/third/";
		String url = alias + "editCrowdActivity.do?id=" + activityId;
		result.put("url", url);
		result.put("alias", alias);
		return result;
	}

	/**
	 * 保存活动模板
	 * @param targetTemplate 众筹模板
	 */
	public void saveForActivity(TargetTemplate targetTemplate){
		if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
			throw new BusinessException("模板内容不能为空");
		}
		Activity activity = activityService.get(targetTemplate.getTargetId());
		if (null == activity){
			throw new BusinessException("找不到众筹项目");
		}

		//保存
		targetTemplate.setInitiatorId(activity.getMember());
		targetTemplateService.insert(targetTemplate);
	}

	/**
	 * 活动短信真实发送
	 *
	 * @param targetTemplate 模板
	 * @param orgId          机构id
	 */
	public boolean activityRealSend(TargetTemplate targetTemplate, String orgId) {
		PackageCount packageCount = packageCountService.getUnique(new PackageCount(orgId, TargetType.PUSH_SMS.getCode()));
		if (packageCount != null && YesNoStatus.YES.getCode().equals(packageCount.getIsOpen())) {
			Integer spareNum = packageCountService.getSpareNum(packageCount.getTotalNum(), packageCount.getUseNum());
			targetTemplate.setSpareNum(spareNum);
		}

		TargetTemplateType targetTemplateType = TargetTemplateType.get(targetTemplate.getType());
		INotifyActivitySendService notifyActivitySendService = activitySendFactory.getSender(targetTemplateType);
		return notifyActivitySendService.send(targetTemplate.getTargetId(), orgId,
				targetTemplate, InstanceWay.ORGANIZATION.getName());
	}

	/**
	 * 消息推送-定时
	 * @param targetTemplate
	 * @param dateTime: 格式为yyyy-MM-dd HH:mm:ss
	 * @param type: 1: 众筹项目 2: 众筹事件
	 * @return
	 */
	@Transactional
	public AjaxResult sendQuartz(TargetTemplate targetTemplate, String dateTime, String behavior, Integer type) {
		AjaxResult ajaxResult = new AjaxResult();
		Date date = null;
		if (StringUtils.isEmpty(dateTime)) {
			return AjaxResult.error("dateTime不能为空");
		}
		if (dateTime.indexOf(":") == dateTime.lastIndexOf(":")) {
			dateTime = dateTime + ":00";
		}
		try {
			date = DateUtils.parse(dateTime, "yyyy-MM-dd HH:mm:ss");
		} catch (ParseException e) {
			logger.error("定时推送短信失败, 时间参数有误 dateTime = {}", dateTime, e);
			ajaxResult.setDescription("定时推送短信失败, 时间参数有误 dateTime = " + dateTime);
			ajaxResult.setSuccess(false);
			return ajaxResult;
		}

		// 定时的时间小于当前时间, 则直接立即执行
		if (date.getTime() < System.currentTimeMillis()) {
			if ("add".equals(behavior)) {
				this.sendAndSave(targetTemplate);
			} else if ("modifyTime".equals(behavior)){
				return AjaxResult.error("时间参数有误, 该时间将永远不会执行 dateTime = " + dateTime);
			} else {
				this.send(targetTemplate.getId());
			}
			return AjaxResult.success();
		}

		targetTemplate.setSendTime(date);
		String tempId = null;
		boolean hasTemp;
		if ("add".equals(behavior)) {
			targetTemplate.setId(null);
			if (Constant.SEND_SHORT_MESSAGE_TYPE_ACTIVITY.equals(type)) {
				tempId = this.save(targetTemplate);
			}
			hasTemp = false;
		} else {
			// 如果是修改发送时间, 需要检测该短信是否已经发送了
			if ("modifyTime".equals(behavior)) {
				TargetTemplate dbTemp = targetTemplateService.get(targetTemplate.getId());
				Date sendTime = dbTemp.getSendTime();
				if (null != sendTime && sendTime.getTime() < System.currentTimeMillis()) {
					return AjaxResult.error("该短信已经发送了, 请刷新页面");
				}
			}
			targetTemplateService.update(targetTemplate);
			tempId = targetTemplate.getId();
			hasTemp = true;
		}

		if (StringUtils.isEmpty(tempId)) {
			return AjaxResult.error("保存定时发送短信模板失败, template = " + targetTemplate);
		}

		String cron = DateUtils.formatDate(date, "s m HH d M ? yyyy");

		final String clazz = "quartzBizSendShortMessage";
		final String method = "send";

		List<Object> params = Lists.newArrayList();
		params.add(type);

		Event event;
		if (hasTemp) {
			event = eventService.findByCode(clazz);
			event.setCronExpression(cron);
			scheduleJobService.dynamicUpdate(event, tempId, SchsduleService.GROUP_SEND_SHORT_MESSAGE, params);
		} else {
			event = new Event();
			event.setWay(com.party.common.constant.Constant.EVENT_AUTO);
			event.setName(SchsduleService.JOB_SEND_SHORT_MESSAGE);
			event.setCode(clazz);
			event.setType("4");
			event.setCronExpression(cron);
			event.setIsSync(0);
			event.setClassName(clazz);
			event.setMethod(method);
			scheduleJobService.dynamicInsert(event, tempId, SchsduleService.GROUP_SEND_SHORT_MESSAGE, params);
		}

		ajaxResult.setSuccess(true);
		return ajaxResult;
	}

	/**
	 * 删除短信
	 * @param id: 模板id
	 * @return
	 */
	@Transactional
	public AjaxResult delQuartzForActivity(String id) {
		if (StringUtils.isEmpty(id)) {
			return AjaxResult.error("短信模板id不能为空");
		}
		TargetTemplate targetTemplate = targetTemplateService.get(id);
		if (null == targetTemplate) {
			return AjaxResult.error("找不到对应的模板 id= " + id);
		}
		// 移除定时器
		final String triggerName = SchsduleService.JOB_SEND_SHORT_MESSAGE.concat(SchsduleService.SEND_SHORT_MESSAGE_LINE).concat(id);
		final String group = SchsduleService.GROUP_SEND_SHORT_MESSAGE;
		scheduleJobService.removeTrigger(triggerName, group);
		// 删除短信
		targetTemplateService.delete(id);
		// 删除存的值在qrtz_data_map
		final String targetId = SchsduleService.PARAMS.concat(SchsduleService.SEND_SHORT_MESSAGE_LINE).concat(id);
		QuartzDataMap quartzDataMap = quartzDataMapService.findByTargetId(targetId);
		if (null != quartzDataMap) {
			quartzDataMapService.delete(quartzDataMap.getId());
		}
		return AjaxResult.success();
	}

	/**
	 * 添加合作渠道
	 *
	 * @param activityId  活动id
	 * @param mobile      手机号码
	 * @param countryCode 区号
	 */
	public void bindZcActivityRelation(String activityId, String mobile, String countryCode) {
		MemberGroup member = memberGroupService.findByPhone(mobile, Constant.MEMBER_ORGANIZATION);
		String memberId;
		if (member == null) {
			memberId = memberGroupBizService.saveCosponsorMember(mobile, countryCode);
		} else {
			memberId = member.getId();
			memberGroupBizService.bindCosponsorRole(member);
		}
		if (StringUtils.isEmpty(memberId)) {
			throw new BusinessException("用户为空");
		}
		Activity activity = activityService.get(activityId);
		String oldCosponsorId = activity.getCosponsorId();
		activity.setCosponsorId(memberId);
		activityService.update(activity);

		if (StringUtils.isNotEmpty(oldCosponsorId)) {
			Integer count = activityService.findByCosponsorId(oldCosponsorId);
			if (null != count && count == 0) {
				memberGroupBizService.unBindCosponsorRole(oldCosponsorId);
			}
		}
	}

	public Map<String, Object> putZipInfo(String key) {
		String zipUrl = null;
		String uploadTime = null;
		String jedisValue = stringJedis.getValue(key);
		if (StringUtils.isNotEmpty(jedisValue)) {
			if (jedisValue.indexOf("sourceUrl") != -1) {
				Map<String, String> map = JSONObject.parseObject(jedisValue, Map.class);
				zipUrl = map.get("sourceUrl");
				uploadTime = map.get("uploadTime");
			} else {
				zipUrl = jedisValue;
			}
		}
		Map<String, Object> map = Maps.newHashMap();
		map.put("zipUrl", zipUrl);
		map.put("zipUploadTime", uploadTime);
		return map;
	}

    /**
     * 迁移行知公社发布的活动到子账号下
     *
     * @param title        查询的标题
     * @param xzgsMemberId 行知公社用户id
     * @param username     子账号的用户名
     * @author yifeng
     * @date 11:05 2019/11/12
     **/
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void xzgsActivityDataMigration(String title, String xzgsMemberId, String username) {
        String memberId = "";
        List<String> activityIds = activityService.getXzgsActivityList(title, xzgsMemberId);
        if (activityIds.size() > 0) {
            MemberGroup memberGroup = memberGroupService.findByUserName(username);
            memberId = memberGroup.getId();
        }
        for (String activityId : activityIds) {
            activityService.updateMember(activityId, memberId);

            this.uploadQrCode(memberId, activityId);
        }
    }

    /**
     * 上传相关二维码
     *
     * @param memberId   用户id
     * @param activityId 活动id
     * @author yifeng
     * @date 14:48 2019/11/12
     **/
    public void uploadQrCode(String memberId, String activityId) {
        try {

            // 普通活动
            String filePath = fileBizService.getUploadCIPath(memberId, "activity");
            /*** 详情二维码 ***/
            String fileName = "detail_" + activityId;
            String content = "hd/hd_detail.html?hdId=" + activityId;
            fileBizService.uploadCloudOut(fileName, filePath, content, memberId);

            /*** 签到二维码 ***/
            String bmFileName = "sign_" + activityId;
            String bmContent = "hd/hdbm_sign.html?hdId=" + activityId;
            fileBizService.uploadCloudOut(bmFileName, filePath, bmContent, memberId);

            /*** 分销二维码 ***/
            String fxFileName = "fx_" + activityId;
            String fxContent = this.getDistributionUrl(activityId, memberId);
            fileBizService.uploadCloudOut(fxFileName, filePath, fxContent, memberId);

        } catch (Exception e) {
            logger.error("活动/众筹项目二维码生成异常", e);
        }
    }
}
